#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import fcntl

from ndmp.comm.log import log


class ShareResourceManager:
    """
    使用fcntl实现文件锁，用于多进程间的文件读写，当前实现不支持读取大于内存大小的文件
    由于ndmp单进程读写连续操作，所以采用互斥锁
    :param file_path: 文件名
    """
    def __init__(self, file_path: str, mode):
        try:
            self.f = open(file_path, mode)
            fcntl.flock(self.f, fcntl.LOCK_EX)
        except Exception as e:
            log.error(f"Failed to open file: {e}", exc_info=True)
            self.f = None

    def __del__(self):
        self.close()

    def close(self):
        """
        显式释放锁并关闭文件。幂等方法，多次调用不会产生副作用。
        """
        if self.f:
            try:
                # 检查文件是否已经关闭
                if not self.f.closed:
                    # 释放锁
                    fcntl.flock(self.f, fcntl.LOCK_UN)
                    # 关闭文件
                    self.f.close()
            except Exception as e:
                log.error(f"Failed to unlock or close file: {e}", exc_info=True)
            finally:
                # 确保 self.f 被置为 None，避免重复操作
                self.f = None

    def read(self):
        if self.f:
            self.f.seek(0)
            return self.f.read()
        return ""

    def update(self, json_str):
        if self.f:
            self.f.seek(0)
            self.f.truncate()
            self.f.write(json_str)
            self.f.flush()